The calculation of electric fields is done by classes 
derived from the abstract base class \texttt{ComponentBase}. 
The key functions are 
\begin{lstlisting}
void ElectricField(const double x, const double y, const double z,
                   double& ex, double& ey, double& ez,
                   Medium*& m, int& status);
void ElectricField(const double x, const double y, const double z,
                   double& ex, double& ey, double& ez, double& v);
Medium* GetMedium(const double& x, const double& y, const double& z);
\end{lstlisting}
\begin{description}
  \item[x, y, z] 
  position where the electric field (medium) is to be determined
  \item[ex, ey, ez, v] 
  electric field and potential at the given position
  \item[m] pointer to the medium at the given position; 
  if there is no medium at this location, a null pointer is returned
  \item[status] status flag indicating where the point is located
  (see Table~\ref{Tab:StatusFlagsField})
\end{description}

\begin{table} 
  \centering
  \begin{tabular}{l l}
  \toprule
  value & meaning \\
  \midrule
    0   & inside a drift medium \\
  \(> 0\) & inside a wire \\
   -1 \dots -4  &  on the side of a plane where no wires are \\
   -5   & inside the mesh, but not in a drift medium \\
   -6   & outside the mesh \\
  \bottomrule
  \end{tabular}
  \caption{Status flags for electric fields.}
  \label{Tab:StatusFlagsField}
\end{table}

\section{Defining the geometry}

As mentioned above, the purpose of \texttt{Component} classes is to 
provide, for a given location, the electric (and magnetic) field and a pointer to the 
\texttt{Medium} (if available).
For the latter task, it is obviously necessary to specify the geometry 
of the device. 
In case of field maps, the geometry is already defined in the field solver. 
It is, therefore, sufficient to associate the materials 
of the field map with the corresponding \texttt{Medium} classes. 

For analytic fields, the geometry is, in general, given by the 
cell layout.

For other components (\textit{e. g.} user-parameterized fields), 
the geometry has to be defined separately. 

Simple structures can be described by the native geometry (\texttt{GeometrySimple}), which has only a very restricted repertoire of shapes (solids). 
At present, the available solids are
\begin{itemize}
  \item
  \texttt{SolidBox}, 
  \item
  \texttt{SolidTube}, 
  \item
  \texttt{SolidHole}, 
  \item
  \texttt{SolidRidge}, and
  \item
  \texttt{SolidSphere}.
\end{itemize} 
A description of these classes is given in Appendix \ref{Sec:Solids}.

As an example, we consider a gas-filled tube with a diameter of 1\,cm and 
a length of 20\,cm (along the \(z\)-axis), centred at the origin:
\begin{lstlisting}
// Create the medium.
MediumMagboltz gas;
// Create the geometry.
GeometrySimple geo;
// Dimensions of the tube
double rMin = 0., rMax = 0.5, halfLength = 10.;
SolidTube tube(0., 0., 0., rMin, rMax, halfLength);
// Add the solid to the geometry, together with the gas inside.
geo.AddSolid(&tube, &gas);
\end{lstlisting}

Solids may overlap. 
When the geometry is scanned 
(triggered, for instance, by calling \texttt{GetMedium}), the  
first medium found is returned. 
The sequence of the scan is reversed with respect to the 
assembly of the geometry. 
Hence, the last medium added to the geometry is considered the innermost. 

For more complex structures, the class \texttt{GeometryRoot} can be used 
which provides an interface to the ROOT geometry (\texttt{TGeo}).
Using \texttt{GeometryRoot}, the above example would look like this:
\begin{lstlisting}
// Create the ROOT geometry.
TGeoManager* geoman = new TGeoManager("world", "geometry");
// Create the ROOT material and medium. 
// For simplicity we use the predefined material "Vacuum".
TGeoMaterial* matVacuum = new TGeoMaterial("Vacuum", 0, 0, 0);
TGeoMedium*   medVacuum = new TGeoMedium("Vacuum", 1, matVacuum);
// Dimensions of the tube
double rMin = 0., rMax = 0.5, halfLength = 10.;
// In this simple case, the tube is also the top volume.
TGeoVolume* top = geoman->MakeTube("TOP", medVacuum, rMin, rMax, halfLength);
geoman->SetTopVolume(top);
geoman->CloseGeometry();
// Create the Garfield medium.
MediumMagboltz* gas = new MediumMagboltz();
// Create the Garfield geometry.
GeometryRoot* geo = new GeometryRoot();
// Pass the pointer to the TGeoManager.
geo->SetGeometry(geoman);
// Associate the ROOT medium with the Garfield medium.
geo->SetMedium("Vacuum", gas); 
\end{lstlisting} 

In either case (\texttt{GeometrySimple} and \texttt{GeometryRoot}),
after assembly the geometry is passed to the \texttt{Component} as a pointer:
\begin{lstlisting}
void SetGeometry(Geometry* geo);
\end{lstlisting}

\subsection{Visualizing the geometry}

Geometries described by \texttt{GeometrySimple} can be viewed 
using the class \texttt{ViewGeometry}. 
\begin{lstlisting}
MediumMagboltz gas;
// Create and setup the geometry.
GeometrySimple geo;
const double r1 = 0.4;
const double r2 = 0.6;
SolidHole hole(0, 0, 0, r1, r2, 1, 1, 1);
hole.SetSectors(4);
geo.AddSolid(&hole, &gas);

// Create a viewer.
ViewGeometry geoView;
geoView.SetGeometry(&geo);
geoView.Plot3d();
\end{lstlisting}
The snippet above will produce a three-dimensional impression of the geometry.
The function \texttt{ViewGeometry::Plot2d()} draws a cut through the solids 
at the current viewing plane, \textit{e. g.} using again the geometry defined above,
\begin{lstlisting}
// ...
ViewGeometry geoView;
geoView.SetPlaneXZ();
geoView.Plot2d();
\end{lstlisting} 

ROOT geometries can be visualized by calling the \texttt{Draw()} function of
\texttt{TGeoManager}. 

The layout of an arrangement of wires, planes and tubes
defined in \texttt{ComponentAnalyticField} 
can be inspected using the class \texttt{ViewCell}.
\begin{lstlisting}
// Create and setup the component.
ComponentAnalyticField cmp;
... 
// Create a viewer.
ViewCell view;
// Set the pointer to the component.
view.SetComponent(&cmp);
// Make a two-dimensional plot of the cell layout.
view.Plot2d();
\end{lstlisting}
Similarly, the function \texttt{ViewCell::Plot3d()} paints
a three-dimensional view of the cell layout.

\section{Field maps}

\subsection{Ansys}

The interpolation of FEM field maps 
created with the program Ansys \cite{ANSYS} 
is dealt with by the classes
\texttt{ComponentAnsys121} and \texttt{ComponentAnsys123}. 
The class names refer to the type of mesh element used by Ansys:
  \begin{itemize}
  \item
  \texttt{ComponentAnsys121} reads two-dimensional field maps 
with 8-node curved quadrilaterals (known as ``plane121'' in Ansys). 
  \item
  \texttt{ComponentAnsys123} reads three-dimensional field maps 
with quadric curved tetrahedra (known as ``solid123'' in Ansys).
  \end{itemize}
The field map is imported with the function
\begin{lstlisting}
bool Initialise(std::string elist, std::string nlist,
                std::string mplist, std::string prnsol, std::string unit);
\end{lstlisting}
\begin{description}
  \item[elist]
  name of the file containing the list of elements 
  (default: \texttt{"ELIST.lis"})
  \item[nlist]
  name of the file containing the list of nodes
  (default: \texttt{"NLIST.lis"})
  \item[mplist]
  name of the file containing the list of materials
  (default: \texttt{"MPLIST.lis"})
  \item[prnsol]
  name of the file containing the nodal solutions
  (default: \texttt{"PRNSOL.lis"})
  \item[unit]
  length unit used in the calculation (default: \texttt{"cm"}, \\ 
  other recognized units are 
  \texttt{"mum"}/\texttt{"micron"}/\texttt{"micrometer"},
  \texttt{"mm"}/\texttt{"millimeter"} and 
  \texttt{"m"}/\texttt{"meter"}).
\end{description}
The return value is \texttt{true} if the map was successfully read. 

In order to enable charge transport and ionization,
the materials in the map need to be associated with \texttt{Medium} classes.
\begin{lstlisting}
// Get the number of materials in the map.
unsigned int GetNumberOfMaterials();
// Associate a material with a Medium class.
void SetMedium(const unsigned int imat, Medium* medium);
\end{lstlisting}
\begin{description}
\item[imat]
index in the list of (field map) materials
\item[medium]
pointer to the \texttt{Medium} class to be associated with this material
\end{description}

The materials in the field map are characterized by the 
relative dielectric constant \(\varepsilon\) and the 
conductivity \(\sigma\). 
These parameters are accessible through the functions
\begin{lstlisting}
double GetPermittivity(const unsigned int imat);
double GetConductivity(const unsigned int imat);
\end{lstlisting}

By default, mesh elements in conductors, \ie materials 
with resistivity equal to zero, are eliminated. This feature can be 
switched on or off using
\begin{lstlisting}
void EnableDeleteBackgroundElements(const bool on = true);
\end{lstlisting}
\begin{description}
  \item[on] flag to delete mesh elements in conductors (\texttt{true}) or keep them (\texttt{false}) 
\end{description}
A weighting field map can be imported using
\begin{lstlisting}
bool SetWeightingField(std::string prnsol, std::string label);
\end{lstlisting}
\begin{description}
  \item[prnsol]
  name of the file containing the nodal solution for the weighting field
  configuration
  \item[label]
  arbitrary name, used for identification of the electrode/signal
\end{description}

The weighting field map has to use the same mesh as the previously 
read ``actual'' field map.

For periodic structures, \textit{e.\,g.} GEMs, one usually models only 
the basic cell of the geometry and applies appropriate symmetry 
conditions to cover the whole problem domain. 
The available symmetry operations are:
\begin{itemize}
  \item
  simple periodicities,
  \item
  mirror periodicities, 
  \item
  axial periodicities, and
  \item
  rotation symmetries.
\end{itemize}

Mirror periodicity means that odd periodic copies of the basic cell 
are mirror images of even periodic copies.
Mirror periodicity and simple periodicity as well as 
axial periodicity and rotation symmetry are, 
obviously, mutually exclusive. 
In case of axial periodicity, the field map has to cover an 
integral fraction of \(2\pi\). 

Periodicities can be set and unset using
\begin{lstlisting}
void EnablePeriodicityX(const bool on);
void EnableMirrorPeriodicityX(const bool on);
void EnableAxialPeriodicityX(const bool on);
void EnableRotationSymmetryX(const bool on);
\end{lstlisting}
\begin{description}
\item[on] flag to enable (\texttt{true}) or disable (\texttt{false}) periodicity. 
\end{description}
Analogous functions are available for \(y\) and \(z\).

In order to assess the quality of the mesh, 
one can retrieve the dimensions of each mesh element using
\begin{lstlisting}
bool GetElement(const unsigned int i, double& vol, double& dmin, double& dmax);
\end{lstlisting}
\begin{description}
\item[i] index of the element
\item[vol] volume/area of the element
\item[dmin, dmax] min./max. distance between two node points
\end{description}

In the following example we make histograms of the aspect ratio and 
element size.
\begin{lstlisting}
ComponentAnsys123* fm = new ComponentAnsys123();
...
TH1F* hAspectRatio = new TH1F("hAspectRatio"; "Aspect Ratio", 100, 0., 50.);
TH1F* hSize = new TH1F("hSize", "Element Size", 100, 0., 30.);
const unsigned int nel = fm->GetNumberOfElements();
// Loop over the elements.
double volume, dmin, dmax;
for (unsigned int i = 0; i < nel; ++i) {
  fm->GetElement(i, volume, dmin, dmax);
  if (dmin > 0.) hAspectRatio->Fill(dmax / dmin);
  hSize->Fill(volume);
}
TCanvas* c1 = new TCanvas();
hAspectRatio->Draw();
TCanvas* c2 = new TCanvas();
c2->SetLogy();
hSize->Draw();
\end{lstlisting}

\subsection{Synopsys TCAD}

Electric fields calculated using the device simulation program 
Synopsys Sentaurus \cite{Synopsys} can be imported with the classes 
\texttt{ComponentTcad2d} and \texttt{ComponentTcad3d}.

The function to import the field map is 
\begin{lstlisting}
bool Initialise(const std::string& gridfilename,
                const std::string& datafilename);
\end{lstlisting}
\begin{description}
  \item[gridfilename]
  name of the mesh file, the extension is typically \texttt{.grd}
  \item[datafilename]
  name of the file containing the nodal solution;
  the filename typically typically ends with \texttt{\_des.dat}
\end{description}

Both files have to be exported in DF-ISE format, 
files in the default TDR format cannot be read.
To convert a TDR file to \texttt{\_.dat} and \texttt{.grd} files, the
Sentaurus tool \texttt{tdx} can be used
\begin{lstlisting}
tdx -dd fieldToConvert.tdr
\end{lstlisting}

The classes have been tested with meshes created with the application 
\texttt{Mesh} which can produce axis-aligned 
two- and three-dimensional meshes.
The only three-dimensional mesh elements \texttt{ComponentTcad3d} 
can deal with are tetrahedra. 
A mesh which consists only of simplex elements 
(triangles in 2D, tetrahedra in 3D), 
can be generated by invoking \texttt{Mesh} with the option \texttt{-t}.

After importing the files, 
the regions of the device where charge transport is to be enabled 
need to be associated with \texttt{Medium} classes. 
\begin{lstlisting}
// Get the number of regions in the device
unsigned int GetNumberOfRegions();
// Associate a region with a Medium class
void SetMedium(const unsigned int ireg, Medium* m);
\end{lstlisting}
\begin{description}
  \item[ireg]
  index in the list of device regions
  \item[medium]
  pointer to the \texttt{Medium} class to be associated with this region
\end{description}

The name of a region can be retrieved with
\begin{lstlisting}
void GetRegion(const unsigned int i, std::string& name, bool& active);
\end{lstlisting}
\begin{description}
  \item[name] 
  label of the region as defined in the device simulation
  \item[active] 
  flag indicating whether charge transport is enabled 
  in this region
\end{description}

Simple periodicities and mirror periodicities along 
\(x\), \(y\), and -- in case of \texttt{ComponentTcad3d} -- \(z\) 
are supported. 
\begin{lstlisting}
void EnablePeriodicityX();
void EnableMirrorPeriodicityX();
\end{lstlisting}

Using TCAD, the weighting field and potential are typically determined 
by first computing the electric field $\mathbf{E}_{0}$ and potential 
$V_{0}$ with all electrodes set at the nominal potentials.
The potential at the electrode to be read out is then increased by a 
small voltage $\Delta V$ and the corresponding electric field $E_{+}$ and 
potential $V_{+}$ are calculated. The weighting field and potential 
are then given by 
\begin{equation*}
  \mathbf{E}_{w} = \frac{1}{\Delta V}\left(\mathbf{E}_{+} - \mathbf{E}_{0}\right), \qquad V_{w} = \frac{1}{\Delta V}\left(V_{+} - V_{0}\right).
\end{equation*}
In \texttt{ComponentTcad2d} and \texttt{ComponentTcad3d} the weighting 
field and potential loaded using
\begin{lstlisting} 
SetWeightingField(const std::string& datfile1, const std::string& datfile2,
                  const double dv); 
\end{lstlisting}
\begin{description}
  \item[datfile1] \texttt{.dat} file containing the solution $\mathbf{E}_0, V_0$,
  \item[datfile2] \texttt{.dat} file containing the solution $\mathbf{E}_+, V_+$,
  \item[dv] potential difference $\Delta V$
\end{description}
The mesh is assumed to be the same as the one for the drift field 
(imported using \texttt{Initialise}).

\subsection{Elmer}

The class \texttt{ComponentElmer} (contributed by J. Renner) allows one to import 
field maps created with the open source field solver Elmer \cite{Elmer}
and the mesh tool Gmsh \cite{Gmsh}. 
A detailed tutorial can be found on the webpage. 

\subsection{CST}

The class \texttt{ComponentCST} (contributed by K.~Zenker) reads field maps 
extracted from CST Studio. More details can be found at 
\href{http://www.desy.de/~zenker/FLC/garfieldpp.html}{http://www.desy.de/~zenker/FLC/garfieldpp.html}.

\subsection{COMSOL}

The class \texttt{ComponentComsol} (contributed by E.~Bodnia) can be used for 
importing field maps computed using COMSOL.
The function to import a field map is 
\begin{lstlisting}
bool Initialise(std::string header = "mesh.mphtxt",
                std::string mplist = "dielectrics.dat",
                std::string field = "field.txt");
\end{lstlisting}
\begin{description}
  \item[header] COMSOL Multiphysics text field (\texttt{.mphtxt}) containing the mesh data.
  \item[field] exported field data. 
\end{description}

\subsection{Regular grids}
\begin{figure}
  \centering
  \begin{tikzpicture}
    \draw[help lines,step=2] (0, 0) grid (6, 4);
    \foreach \x in {0,2,4,6}
    \foreach \y in {0,2,4} {
      \fill (\x,\y) circle (2pt);
    }
    \node[below] at (0,0) {\footnotesize $x_{\text{min}}$};
    \node[below] at (6,0) {\footnotesize $x_{\text{max}}$};
    \node[left] at (0,0) {\footnotesize $y_{\text{min}}$};
    \node[left] at (0,4) {\footnotesize $y_{\text{max}}$};
    \node[above right] at (0,0) {\footnotesize $\left(0,0\right)$};
    \node[above right] at (6,0) {\footnotesize $\left(3,0\right)$};
    \node[above right] at (6,4) {\footnotesize $\left(3,2\right)$};
  \end{tikzpicture}
  \caption{Example of a two-dimensional regular mesh (as used in 
           \texttt{ComponentGrid}) with $4\times3$ grid points, 
           corresponding to $n_{x} = 4, n_{y} = 3$.} 
  \label{Fig:MeshComponentGrid}
\end{figure}
Electric field values on a regular two-dimensional or three-dimensional grid 
can be imported from a text file using the class \texttt{ComponentGrid}. 
The electric field values (and potential) for each point on the grid 
are read in using
\begin{lstlisting}
bool LoadElectricField(const std::string& filename, const std::string& format,
                       const bool withPotential, const bool withFlag,
                       const double scaleX = 1., const double scaleE = 1.,
                       const double scaleP = 1.);
\end{lstlisting}
\begin{description}
  \item[filename]
  name of the ASCII file
  \item[format]
  description of the file format (see below)
  \item[withPotential]
  flag whether the file contains an additional column with the electrostatic potential
  \item[withRegion]
  flag whether the file contains an additional column with an integer value 
  indicating whether the point is in an active medium (1) or not (0).
  \item[scaleX, scaleE, scaleP]
  scaling factors to be applied to the coordinates, electric field values 
  and potentials 
\end{description}
The file should contain one line for each grid point.
The available formats are \texttt{XY}, \texttt{IJ}, \texttt{XYZ}, 
and \texttt{IJK}, the first two for two-dimensional maps, and the 
last two for three-dimensional maps.
In case of \texttt{XY} (\texttt{XYZ}), the first two (three) columns  
contain the $x$, $y$ (and $z$) coordinates of a given point in the 
grid, followed by the electric field values (and potential if available) at 
this point. The class then determines the closest grid point 
and assigns the electric field and potential accordingly.
In case of \texttt{IJ} (\texttt{IJK}) the indices of the grid point 
along $x$, $y$ (and $z$) are specified directly.
The file can include comments (lines starting with \texttt{\#} or \texttt{//}). 

Prior to reading the electric field, the limits and spacing of the grid 
can be set using the function
\begin{lstlisting}
void SetMesh(const unsigned int nx, const unsigned int ny,
             const unsigned int nz, const double xmin, const double xmax,
             const double ymin, const double ymax, const double zmin,
             const double zmax);
\end{lstlisting}
\begin{description}
  \item[nx, ny, nz] 
  number of grid lines along $x$, $y$, $z$
  \item[xmin, xmax, \dots] 
  boundaries of the grid in $x$, $y$, $z$
\end{description}
An example illustrating the parameters defining the mesh and the 
numbering of the grid nodes is shown in Fig.~\ref{Fig:MeshComponentGrid}.
Alternatively, the grid parameters can be read from the file that contains
the electric field/potential. For instance, to specify the 
limits and number of grid lines along $z$, a line like 
\begin{lstlisting}
# ZMIN = -1., ZMAX = 1., NZ = 3 
\end{lstlisting} 
should be included at the beginning of the file.
If the user has not specified the grid explicitly (using \texttt{SetMesh}) 
and the information given in the comment lines is incomplete, the 
class will try to determine the remaining grid parameters from the 
table of coordinates and corresponding electric fields itself.

When retrieving the field/potential at a given point $\left(x, y, z\right)$ 
the class performs a trilinear interpolation between the values at the 
grid nodes surrounding this point. The medium in the domain covered by the mesh 
is set using 
\begin{lstlisting}
void SetMedium(Medium* m);
\end{lstlisting}
A point $\left(x,y,z\right)$ is considered in an active region 
(\ie associated to the medium) if all surrounding grid nodes are 
flagged as active. 

A magnetic field map can be imported using the function
\begin{lstlisting}
bool LoadMagneticField(const std::string& filename, const std::string& format,
                       const double scaleX = 1., const double scaleB = 1.);
\end{lstlisting}
The available formats are the same as for the electric field (except for the 
extra columns for potential and active medium flag).
Prompt and delayed weighting fields/potentials can be imported using
\begin{lstlisting}
bool LoadWeightingField(const std::string& filename, const std::string& format,
                        const bool withPotential,
                        const double scaleX = 1., const double scaleE = 1.,
                        const double scaleP = 1.);
bool LoadWeightingField(const std::string& filename, const std::string& format,
                        const double time, const bool withPotential,
                        const double scaleX = 1., const double scaleE = 1.,
                        const double scaleP = 1.);
\end{lstlisting}

\begin{figure}
  \centering
  \begin{tikzpicture}
    \draw[help lines,step=2] (0, 0) grid (6, 4);
    \foreach \x in {1,3,5}
    \foreach \y in {1,3} {
      \fill (\x,\y) circle (2pt);
    }
    \node[below] at (0,0) {\footnotesize $x_{\text{min}}$};
    \node[below] at (6,0) {\footnotesize $x_{\text{max}}$};
    \node[left] at (0,0) {\footnotesize $y_{\text{min}}$};
    \node[left] at (0,4) {\footnotesize $y_{\text{max}}$};
    \node[above right] at (1,1) {\footnotesize $\left(0,0\right)$};
    \node[above right] at (5,1) {\footnotesize $\left(2,0\right)$};
    \node[above right] at (5,3) {\footnotesize $\left(2,1\right)$};
  \end{tikzpicture}
  \caption{Example of a two-dimensional regular mesh (as used in 
           \texttt{ComponentVoxel}) with $3\times2$ cells, 
           corresponding to $n_{x} = 3, n_{y} = 2$.} 
  \label{Fig:MeshComponentVoxel}
\end{figure}

The class \texttt{ComponentVoxel} is similar to \texttt{ComponentGrid} 
but uses a different definition of the mesh. 
An example illustrating the parameters of the mesh and the numbering of 
the voxels/cells is shown in Fig.~\ref{Fig:MeshComponentVoxel}.
As a first step, the mesh needs to be defined using the function
\begin{lstlisting}
void SetMesh(const unsigned int nx, const unsigned int ny,
             const unsigned int nz, const double xmin, const double xmax,
             const double ymin, const double ymax, const double zmin,
             const double zmax);
\end{lstlisting}
\begin{description}
  \item[nx, ny, nz] 
  number of rows/columns of cells along $x$, $y$, $z$
  \item[xmin, xmax, \dots] 
  boundaries of the grid in $x$, $y$, $z$
\end{description}
The electric field values (and potential) for each voxel are imported using 
\begin{lstlisting}
bool LoadElectricField(const std::string& filename, const std::string& format,
                       const bool withPotential, const bool withRegion,
                       const double scaleX = 1., const double scaleE = 1.,
                       const double scaleP = 1.);
\end{lstlisting}
\begin{description}
  \item[filename]
  name of the ASCII file
  \item[format]
  description of the file format (see \texttt{ComponentGrid})
  \item[withPotential]
  flag whether the file contains an additional column with the electrostatic potential
  \item[withRegion]
  flag whether the file contains an additional column with an integer value 
  corresponding to the region index (each region can be associated with a different medium)
  \item[scaleX, scaleE, scaleP]
  scaling factors to be applied to the coordinates, electric field values 
  and potentials 
\end{description}
The medium to be associated with a given region can be set using
\begin{lstlisting}
void SetMedium(const unsigned int i, Medium* m);
\end{lstlisting}
\begin{description}
  \item[i] index of the region
\end{description}
If the regions are not assigned explicitly when importing the electric field, 
all voxels are assumed to belong to the same region (index 0).

By default, the field and potential are assumed to be constant within 
a voxel. Alternatively, the fields/potentials given in the field map file
can be interpreted to be the values at the voxel centres and the 
fields/potentials at intermediate points be determined by trilinear interpolation.
This feature can be activated using the function
\begin{lstlisting}
void EnableInterpolation(const bool on = true);
\end{lstlisting} 
 
\subsection{Visualizing the mesh}

For visualizing the mesh imported from a FEM field map, the class 
\texttt{ViewFEMesh} (written by J. Renner) is available. 
Using 
\begin{lstlisting}
void ViewFEMesh::SetViewDrift(ViewDrift* driftView);
\end{lstlisting}
a \texttt{ViewDrift} object can be attached to the mesh viewer. 
The function
\begin{lstlisting}
bool ViewFEMesh::Plot();
\end{lstlisting}
then allows draws a two-dimensional projection of the drift lines stored in the  
\texttt{ViewDrift} class together with the mesh. 
The plot can be customized using 
\begin{lstlisting}
void SetColor(int matid, int colorid);
void SetFillColor(int matid, int colorid);
void SetFillMesh(bool fill);
\end{lstlisting}
\begin{description}
  \item[matid] material index in the field map
  \item[colorid] index of the ROOT color with which all elements of material 
                 \texttt{matid} are to be drawn 
  \item[fill] flag indicating whether to draw a wireframe mesh (\texttt{false}) 
              or filled elements
\end{description}
As an illustration consider the following example 
(suppose that \texttt{fm} is a pointer to a field map component 
and \texttt{driftView} is a pointer to a \texttt{ViewDrift} class) 
\begin{lstlisting}
  TCanvas* c1 = new TCanvas();
  ViewFEMesh* meshView = new ViewFEMesh();
  meshView->SetCanvas(c1);
  // Set the component.
  meshView->SetComponent(fm);
  // Set the viewing plane.
  meshView->SetPlane(0, -1, 0, 0, 0, 0);
  meshView->SetFillMesh(false);
  meshView->SetViewDrift(driftView);
  meshView->SetArea(-0.01, -0.01, -0.03, 0.01, 0.01, 0.01);
  meshView->Plot();
\end{lstlisting}

\section{Analytic fields}

For two-dimensional geometries consisting of wires, planes and tubes, 
semi-analytic calculation techniques -- based essentially 
on the capacitance matrix method -- are implemented.

\subsection{Describing the cell}
The medium to be associated with the active region of the cell 
is set using
\begin{lstlisting}
SetMedium(Medium* medium);
\end{lstlisting}
Wires, tubes and planes can be added to the cell layout by means of the 
following functions:
\begin{lstlisting}
// Add a wire
void AddWire(const double x, const double y, const double d,
             const double v, const std::string& label, 
             const double length = 100.,
             const double tension = 50., const double rho = 19.3);
// Add a tube
void AddTube(const double r, const double v, 
             const int nEdges, const std::string& label);
// Add a plane at constant x
void AddPlaneX(const double x, const double v, const std::string& label);
// Add a plane at constant y
void AddPlaneY(const double y, const double v, const std::string& label);

\end{lstlisting} 

In all of these functions, the potential \texttt{v} (in V) 
and a label (used for signal calculation) 
have to be supplied as parameters.
 
For wires, the center of the wire (\texttt{x, y}) 
and its diameter (\texttt{d}) need to be specified. 
Optional parameters are the wire length, the tension (more precisely, the 
mass in g of the weight used to stretch the wire during the assembly) and 
the density (in g\,/\,cm\(^{3}\)) of the wire material. 
These parameters have no influence on the electric field. 
The number of wires that can be added is not limited.

Tube-specific parameters are the radius\footnote{For non-circular tubes, this parameter is the distance between the origin and any of the edges.} (\texttt{r}) and the number of edges, which determines the shape of the tube:
  \begin{itemize}
    \item
    \(n = 0\): cylindrical pipe
    \item
    \(3 \le n \le 8\): regular polygon 
  \end{itemize}
There can be only one tube in a cell. 
The tube is always centered at the origin \(\left(0, 0\right)\).

Planes are described by their coordinates. 
A cell can have at most two \(x\) and two \(y\) planes. 
Planes and tubes cannot be used together in the same cell.

The geometry can be reset (thereby deleting all wires, planes and tubes) by
\begin{lstlisting}
void Clear();
\end{lstlisting}

Before assembling and inverting the capacitance matrix, 
a check is performed whether the provided geometry matches the requirements.
If necessary, the planes and wires are reordered. 
Wires outside the tube or the planes as well as overlapping wires are removed.

\subsection{Cylindrical geometries}

By default, the wire coordinates are specified in Cartesian coordinates and 
the planes are parallel to the $x$ or $y$ axis.
Calling 
\begin{lstlisting}
void SetPolarCoordinates();
\end{lstlisting} 
switches to a polar coordinate system. This can be useful for 
certain types of cells which are more conveniently described in polar coordinates
$\left(r, \phi\right)$, for instance because of the presence of a circular plane. 

Internally, the class uses log-polar coordinates $\left(\rho, \phi\right)$, 
where the angular coordinate $\phi$ is the same as in polar coordinates, 
and $\rho = \ln r$. The transformation\footnote{
Using complex numbers, the transformation can be written as 
$x + \text{i}y = \exp\left(\rho + \text{i}\phi\right)$.}
\begin{equation*}
\left(x, y\right) = \text{e}^{\rho}\left(\cos\phi, \sin\phi\right)
\end{equation*}
is a conformal mapping\footnote{This implies that the Laplace equation in log-polar coordinates has the same form as in Cartesian coordinates.} 
which translates circles to lines at constant $\rho$. 
After calculating the field in internal coordinates, it is transformed back to 
Cartesian coordinates using
\begin{equation*}
\begin{pmatrix}E_{x}\\E_{y}\end{pmatrix} = \text{e}^{\rho}
\begin{pmatrix}\cos\phi & -\sin\phi \\ \sin\phi & \cos\phi\end{pmatrix}
\begin{pmatrix}E_{\rho}\\E_{\phi}\end{pmatrix}. 
\end{equation*}

By calling 
\begin{lstlisting}
void SetCartesianCoordinates();
\end{lstlisting} 
one can change back to Cartesian coordinates. 
Mixed coordinates are not permitted; when switching from Cartesian to polar 
coordinates or vice versa the description of the cell is reset.

In order to add a wire 
to the cell, the same function is used 
for both Cartesian and polar coordinates. In the latter case, the 
first coordinate corresponds to the radius of the wire (in cm), 
and the second coordinate corresponds to the angle (in degrees). 
A wire may not be positioned at the origin if polar coordinates are being used.

Planes at constant radius or at constant angle are specified using
\begin{lstlisting}
void AddPlaneR(const double r, const double voltage, const std::string& label);
void AddPlanePhi(const double phi, const double voltage, const std::string& label);
\end{lstlisting}
\begin{description}
  \item[r] radius of the plane (in cm),
  \item[phi] angle of the plane (in degrees).
\end{description}

The following simple example generates a pie wedge with a wire inside.
\begin{lstlisting}
ComponentAnalyticField cmp;
cmp.SetPolarCoordinates();
const double r = 2.;
cmp.AddPlaneR(r, 0., "r");
cmp.AddPlanePhi( 0., 0., "phi1");
cmp.AddPlanePhi(60., 0., "phi2");
cmp.AddWire(0.5 * r, 30., 50.e-4, 500., "w");
\end{lstlisting}

\subsection{Periodicities}
The class supports simple periodicity in \(x\) and \(y\) direction.
The periodic lengths are set using
\begin{lstlisting}
void SetPeriodicityX(const double s);
void SetPeriodicityY(const double s);
\end{lstlisting}

When working in polar coordinates, one can set the $\phi$ periodicity 
using
\begin{lstlisting}
void SetPeriodicityPhi(const double s);
\end{lstlisting} 
\begin{description}
  \item[s] angular period (in degrees).
\end{description}
If the $\phi$ periodicity is not set explicitly by the user, 
a cyclic boundary condition with a period of $2\pi$ is imposed.

Radial periodicity is not supported since the internal coordinate 
$\rho$ is not linear in $r$.

\subsection{Cell types}

Internally, cells are classified as belonging to one of these types:
\begin{description}
  \item[A]
  non-periodic cells with at most one \(x\) and one \(y\) plane
  \item[B1X]
  \(x\)-periodic cells without \(x\) planes and at most one \(y\) plane
  \item[B1Y]
  \(y\)-periodic cells without \(y\) planes and at most one \(x\) plane
  \item[B2X]
  cells with two \(x\) planes and at most one \(y\) plane
  \item[B2Y]
  cells with two \(y\) planes and at most one \(x\) plane
  \item[C1]
  doubly periodic cells without planes
  \item[C2X]
  doubly periodic cells with \(x\) planes
  \item[C2Y]
  doubly periodic cells with \(y\) planes
  \item[C3]
  doubly periodic cells with \(x\) and \(y\) planes
  \item[D1]
  round tubes without axial periodicity
  \item[D2]
  round tubes with axial periodicity
  \item[D3]
  polygonal tubes without axial periodicity
\end{description}

After the cell has been assembled and initialized, the cell type can be 
retrieved by the function
\begin{lstlisting}
std::string GetCellType();
\end{lstlisting}

\subsection{Dipole moments}
By default, \texttt{ComponentAnalyticField} uses the thin-wire approximation
for computing the electric field and potential. In this approach, 
dipole and higher-order terms are neglected which is usually a good   
approximation if the wire spacing is large compared to the diameter.
One can request dipole terms to be included in the calculation using
\begin{lstlisting}
void EnableDipoleTerms(const bool on = true);
\end{lstlisting}
Dipole terms are currently implemented only for cell types 
A, B1X, B1Y, B2X and B2Y.
To investigate whether dipole and higher order terms are significant, 
one can use the function
\begin{lstlisting}
bool MultipoleMoments(const unsigned int iw, const unsigned int order = 4,
                      const bool print = false, const bool plot = false, 
                      const double rmult = 1.,
                      const double eps = 1.e-4, const unsigned int nMaxIter = 20);
\end{lstlisting} 
\begin{description}
  \item[iw] index of the wire for which the multipole decomposition should be done,
  \item[order] order of the highest multipole moment to be taken into account,
  \item[print] flag to request verbose output during the minimisation step,
  \item[plot] flag to create a plot of the result of the multipole fit,
  \item[rmult] distance (in units of the wire radius) at which the potential 
               is to be calculated,
  \item[eps] ``small number'' used by the minimisation function to calculate the derivative matrix,
  \item[nMaxIter] max. number of iteration in the minimisation.
\end{description}

\subsection{Weighting fields}

The weighting field calculation for a readout group 
-- \textit{i.\,e.} all elements (wires, planes, etc.) with the same label --
is activated by the function
\begin{lstlisting}
void AddReadout(const std::string& label);
\end{lstlisting}
In addition to the weighting fields of 
the elements used for the calculation of the 
(actual) electric field, 
the weighting field for a strip segment of a plane 
can also be calculated. 
Strips can be defined using
\begin{lstlisting}
void AddStripOnPlaneX(const char direction, const double x,
                      const double smin, const double smax,
                      const char std::string, const double gap = -1.);
void AddStripOnPlaneY(const char direction, const double y,
                      const double smin, const double smax,
                      const std::string label, const double gap = -1.);
\end{lstlisting} 
\begin{description}
  \item[direction]
  orientation of the strip (\texttt{'y'} or \texttt{'z'} 
  in case of \(x\)-planes, \texttt{'x'} or \texttt{'z'} 
  in case of \(y\)-planes
  \item[x, y] coordinate of the plane on which the strip is located
  \item[smin, smax] min. and max. coordinate of the strip
\end{description}
The strip weighting field is calculated using an analytic expression for  
the field between two infinite parallel plates which are kept at 
ground potential except for the strip segment, which is raised to 1~V.
The anode-cathode distance \(d\) to be used for the evaluation of this 
expression can be set by the user (variable \texttt{gap} in 
\texttt{AddStripOnPlaneX}, \texttt{AddStripOnPlaneY}). 
If this variable is not specified (or set to a negative value), 
the following default values are used:
\begin{itemize}
  \item
  if two planes are present in the cell, \(d\) is  
  assumed to be the distance between those planes;
  \item
  if only one plane is present, \(d\) is taken to be 
  the distance to the nearest wire.
\end{itemize}

Similarly, pixels can be defined using
\begin{lstlisting}
void AddPixelOnPlaneX(const double x, const double ymin, const double ymax,
                      const double zmin, const double zmax,
                      const std::string& label, const double gap = -1.);
void AddPixelOnPlaneY(const double y, const double xmin, const double xmax,
                      const double zmin, const double zmax,
                      const std::string& label, const double gap = -1.);
\end{lstlisting}
Pixel weighting fields are calculated using the expressions given in 
Ref.~\cite{Riegler2014}.

When working in polar coordinates, strips and pixels are defined using
\begin{lstlisting}
void AddStripOnPlaneR(const char direction, const double r, const double smin    ,
                      const double smax, const std::string& label,
                      const double gap = -1.);
void AddStripOnPlanePhi(const char direction, const double phi, const double     smin,
                        const double smax, const std::string& label,
                        const double gap = -1.);
void AddPixelOnPlaneR(const double r,
                      const double phimin, const double phimax,
                      const double zmin, const double zmax,
                      const std::string& label, const double gap = -1.);
void AddPixelOnPlanePhi(const double phi,
                        const double rmin, const double rmax,
                        const double zmin, const double zmax,
                        const std::string& label, const double gap = -1.);
\end{lstlisting} 
Valid strip directions are \texttt{'p'} ($\phi$) or \texttt{'z'} for 
circular planes and \texttt{'r'} or \texttt{'z'} for $\phi$ planes.

\section{Other components}

For simple calculations, the class \texttt{ComponentConstant} can be used. 
As the name implies, it provides a uniform electric field. 
The electric field and potential can be specified using
\begin{lstlisting}
void SetElectricField(const double ex, const double ey, const double ez);
void SetPotential(const double x, const double p, const double z, const double v);
\end{lstlisting}
\begin{description}
  \item[ex, ey, ez]
  components of the electric field
  \item[x, y, z]
  coordinates where the potential is specified
  \item[v]
  voltage at the given position
\end{description}
The weighting field and potential can be set using
\begin{lstlisting}
void SetWeightingField(const double wx, const double wy, const double wz,
                       const std::string label);
void SetWeightingPotential(const double x, const double y, const double z,
                           const double v);
\end{lstlisting}
\begin{description}
  \item[wx,wy,wz] components of the weighting field
  \item[label] identifier of the weighting field/electrode
  \item[x, y, z] coordinates where the weighting potential is specified
  \item[v] weighting potential at the given position 
\end{description}

The class \texttt{ComponentUser} takes the electric field and potential
from a user-defined function.
\begin{lstlisting}
void SetElectricField(std::function<void(const double, const double, const double, 
                                         double& double&, double&)>);
void SetPotential(std::function<void(const double, const double, const double, 
                                     double&)>);
\end{lstlisting}
\begin{description}
  \item[f] user function
\end{description}
Similar functions are available to set the weighting field and potential,
and the magnetic field.

As an example, let us consider the electric field in the bulk 
of an overdepleted planar silicon sensor, given by
\begin{equation*}
E\left(x\right) = \frac{V - V_{\text{dep}}}{d} + 
                    2x \frac{V_{\text{dep}}}{d^{2}},
\end{equation*}
where \(V\) is the applied bias voltage, \(V_{\text{dep}}\) is 
the depletion voltage, and \(d\) is the thickness of the diode.
\begin{lstlisting}
auto efield = [](const double x, const double y, const double z,
                 double& ex, double& ey, double& ez) { 

  // Depletion voltage
  const double vdep = 160.;
  // Applied voltage
  const double v = 200.;
  // Detector thickness
  const double d = 0.1;

  ey = ez = 0.;
  ex = (v - vdep) / d + 2 * x * vdep / (d * d);
};
ComponentUser cmp;
cmp.SetElectricField(efield);
\end{lstlisting}

\section{Visualizing the field}

The class \texttt{ViewField} provides some basic functions 
for plotting the potential and field of a component.

The functions 
\begin{lstlisting}
void PlotContour(const std::string& option = "v");
void Plot(const std::string& option = "v", const std::string& drawopt = "");
\end{lstlisting}
create a contour plot or another two-dimensional plot in the chosen viewing plane.
The quantity to be plotted is set using the parameter \texttt{option} 
(see Table~\ref{Tab:ViewFieldOptionStrings}).
\begin{table}
  \centering
  \caption{\texttt{ViewField} option strings and corresponding quantities.}
  \label{Tab:ViewFieldOptionStrings}
  \begin{tabular}{l l} 
    \toprule
    Quantity & \texttt{option} \\
    \midrule
    Potential & \texttt{"v"}, \texttt{"p"}, \texttt{"phi"} \\
    Magnitude of the field ($\left|\mathbf{E}\right|$) & \texttt{"e"}, \texttt{"mag"}, \texttt{"norm"} \\
    $x$-component of the field ($E_{x}$) & \texttt{"ex"} \\ 
    $y$-component of the field ($E_{y}$) & \texttt{"ey"} \\ 
    $z$-component of the field ($E_{z}$) & \texttt{"ez"} \\ 
    \bottomrule
  \end{tabular}
\end{table}
The parameter \texttt{drawopt} is passed on to the function \texttt{Draw()} of the
ROOT \texttt{TF2} class and sets the plotting options. For instance,
\begin{lstlisting}
ViewField view;
view.Plot("v", "SURF4");
\end{lstlisting}
will create a surface plot of the potential.

The function 
\begin{lstlisting}
void PlotProfile(const double x0, const double y0, const double z0,
                 const double x1, const double y1, const double z1,
                 const std::string& option = "v");
\end{lstlisting}
plots the potential or field (depending on the parameter \texttt{option}) 
along the line  
\(\left(x_{0}, y_{0}, z_{0}\right) \rightarrow 
  \left(x_{1}, y_{1}, z_{1}\right)\).

Similar functions are available for visualizing weighting potentials and fields.
\begin{lstlisting}
void PlotContourWeightingField(const std::string& label, const std::string& option);
void PlotWeightingField(const std::string& label, const std::string& option,
                        const std::string& drawopt);
void PlotProfileWeightingField(const std::string& label,
                   const double x0, const double y0, const double z0,
                   const double x1, const double y1, const double z1,
                   const std::string& option = "v");
\end{lstlisting}
\begin{description}
  \item[label] identifier of the electrode for which to plot the weighting field/potential.
\end{description}

The component or sensor from which to retrieve the field to be plotted 
is set by means of
\begin{lstlisting}
void SetComponent(ComponentBase* c);
void SetSensor(Sensor* s);
\end{lstlisting}

The viewing plane and the region to be drawn 
can be specified using
\begin{lstlisting}
void SetArea(const double xmin, const double ymin, const double xmax, const double ymax);
void SetPlane(const double fx, const double fy, const double fz,
              const double x0, const double y0, const double z0);
void Rotate(const double angle);
\end{lstlisting}
\begin{description}
  \item[xmin, ymin, xmax, ymax] plot range in ``local coordinates'' (in the current viewing plane).
  \item[fx, fy, fz] normal vector of the plane.
  \item[x0, y0, z0] in-plane point.
  \item[angle] rotation angle (in radian).
\end{description}
By default, the viewing plane is the $x-y$ plane (at $z = 0$) and the 
plot range is retrieved from the bounding box of the component/sensor.
The default viewing plane can be restored using 
\begin{lstlisting}
void SetPlaneXY();
\end{lstlisting}
and the feature to determine the plot area from the bounding box can be activated using 
\begin{lstlisting}
void SetArea();
\end{lstlisting}
 
The density of the plotting grid can be set using
\begin{lstlisting}
void SetNumberOfSamples1d(const unsigned int n);
void SetNumberOfSamples2d(const unsigned int nx, const unsigned int ny);
\end{lstlisting}
\begin{description}
  \item[n, nx, ny]
  number of points in \(x\) and \(y\) direction 
  (default for one-dimensional plots: \(n = 1000\);
   default for two-dimensional plots: \(n_{x} = n_{y} = 200\)) 
\end{description}

The number of contour levels can be set using
\begin{lstlisting}
void SetNumberOfContours(const unsigned int n);
\end{lstlisting}

By default, the voltage range is retrieved from the 
minimum and maximum values of the 
potential in the component/sensor, and
the range of the electric and weighting fields is
``guessed'' by taking random samples.
This feature can be switched on or off using the function
\begin{lstlisting}
void EnableAutoRange(const bool on = true, const bool samplePotential = true);
\end{lstlisting}
The flag \texttt{samplePotential} indicates whether the range of the 
potential should be determined by random sampling or if \texttt{ViewField}
should first try to retrieve it from the component/sensor. 

If the ``auto-range'' feature is disabled,
the range of the function to be plotted needs to be set using
\begin{lstlisting}
void SetVoltageRange(const double vmin, const double vmax);
void SetElectricFieldRange(const double emin, const double emax);
void SetWeightingFieldRange(const double wmin, const double wmax);
\end{lstlisting}

\section{Inspecting the field}
\texttt{ComponentBase} provides functions for inspecting the field, 
in particular for determining the electric flux over a surface.
\begin{lstlisting}
double IntegrateFluxSphere(const double xc, const double yc, const double zc,
                           const double r, const unsigned int nI = 20);
\end{lstlisting}
calculates the charge (in fC) enclosed in a sphere of radius $r$ centred at 
$\left(x_{c}, y_{c}, z_{c}\right)$ using Gauss's law, \ie by 
integrating the normal component of the electric field over the 
surface of the sphere, 
\begin{equation*}
  Q = \varepsilon_{0} \oint \mathbf{E}\cdot \text{d}\mathbf{A}.
\end{equation*}  
Similarly,
\begin{lstlisting}
double IntegrateFluxCircle(const double xc, const double yc, 
                           const double r, const unsigned int nI = 50);
\end{lstlisting}
calculates the line charge (in fC\,/\,cm) contained in a circle of radius $r$ 
centred at $\left(x_{c}, y_{c}\right)$.  
The integrations are performed using six-point Gaussian quadrature. 
The number of integration intervals can be set as a parameter. 

The integral of the flux over a parallelogram can be calculated using 
the function
\begin{lstlisting}
double IntegrateFluxParallelogram(const double x0, const double y0, const double z0,
                                  const double dx1, const double dy1, const double dz1,
                                  const double dx2, const double dy2, const double dz2,
                                  const unsigned int nU = 20, const unsigned int nV = 20); 
\end{lstlisting}
\begin{description}
  \item[x0,y0,z0] coordinates of one of the corners of the parallelogram,
  \item[dx1,dy1,dz1] direction vector from $\left(x_{0}, y_{0}, z_{0}\right)$ 
                     to one of the adjacent corners,
  \item[dx2,dy2,dz2] direction vector to the other adjacent corner,
  \item[nU,nV] number of integration intervals along the two directions.
\end{description}
The result is given in units of V\,cm.
\section{Sensor}

The \texttt{Sensor} class can be viewed as a composite of components. 
In order to obtain a complete description of a detector, 
it is sometimes useful to combine fields from different 
\texttt{Component} classes.
For instance, one might wish to use a field map for the electric field, 
calculate the weighting field using analytic methods, 
and use a parameterized \(B\) field. 
Superpositions of several electric, magnetic and weighting fields are also possible. 


Components are added using
\begin{lstlisting}
void AddComponent(ComponentBase* comp);
void AddElectrode(ComponentBase* comp, std::string label);
\end{lstlisting}
While \texttt{AddComponent} tells the \texttt{Sensor} that the 
respective \texttt{Component} should be included in the calculation 
of the electric and magnetic field, 
\texttt{AddElectrode} requests the weighting field named \texttt{label} 
to be used for computing the corresponding signal.

To deactivate (or activate) a component after having added it, the 
function
\begin{lstlisting}
void EnableComponent(const unsigned int i, const bool on);
\end{lstlisting}
can be used. Components that have been deactivated are not taken into 
account when calculating the field but are not removed from the list.

To reset the sensor, thereby removing all components and electrodes, use
\begin{lstlisting}
void Clear();
\end{lstlisting}

The total electric and magnetic fields 
(sum over all components) at a given position are accessible through 
the functions \texttt{ElectricField} and \texttt{MagneticField}.
The syntax is the same as for the corresponding functions of the 
\texttt{Component} classes.
Unlike the fields, materials cannot overlap. 
The function \texttt{Sensor::GetMedium}, therefore, 
returns the first valid drift medium found. 
 
The \texttt{Sensor} acts as an interface to the transport classes.

For reasons of efficiency, it is sometimes useful to restrict 
charge transport, ionization and similar calculations to a 
certain region of the detector.
This ``user area'' can be set by
\begin{lstlisting}
void SetArea(double xmin, double ymin, double zmin,
             double xmax, double ymax, double zmax);
\end{lstlisting} 
\begin{description}
\item[xmin, \dots, zmax]
corners of the bounding box within which transport is enabled. 
\end{description}
Calling \texttt{SetArea()} (without arguments) sets the 
user area to the envelope of all components (if available).

In addition, the \texttt{Sensor} class takes care of 
signal calculations (Chapter~\ref{Chap:Signals}).

